﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Threading;
using System.Windows.Forms;
using Devv.Core.Utils;
using Devv.MonFiMailer.Properties;

namespace Devv.MonFiMailer
{
	public partial class MainForm : Form
	{
		#region Properties

		private List<String> Files { get; set; }
		private List<String> Sent { get; set; }
		private Int32 ErrorCount { get; set; }
		private Int32 SentCount { get; set; }
		private DateTime LastSent { get; set; }

		#endregion

		#region Constructor

		public MainForm()
		{
			InitializeComponent();

			Files = new List<String>();
			Sent = new List<String>();

			ErrorCount = 0;
		}

		#endregion

		#region Main methods

		private void MainForm_Load(object sender, EventArgs e)
		{
			txtPath.Text = Program.Options.FolderPath;
			txtFilter.Text = Program.Options.FolderFilter;
			chkSubDir.Checked = Program.Options.IncludeSubDir;

			txtServer.Text = Program.Options.SmtpServer;
			numPort.Value = Program.Options.SmtpPort;
			chkSSL.Checked = Program.Options.SmtpSSL;
			txtUser.Text = Program.Options.SmtpUser;
			txtPassword.Text = Program.Options.SmtpPassword;

			txtFrom.Text = Program.Options.EmailFrom;
			txtTo.Text = Program.Options.EmailTo;
			txtSubject.Text = Program.Options.EmailSubject;
			numPerMinute.Value = Program.Options.PerMinute;
		}

		private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			Program.Options.Save();

			Int32 i = 0;
			
			try
			{
				for (i = 0; i < Sent.Count; i++)
				{
					//File.Delete(Sent[i]);
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(Sent[i] + Environment.NewLine + Environment.NewLine + ex);
			}

			e.Cancel = false;
		}

		#endregion

		#region Tabs and general UI

		private void tabPages_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (tabPages.SelectedIndex == 0)
			{
				imgLog.Visible = false;
				imgOptions.Visible = true;
			}
			else
			{
				imgOptions.Visible = false;
				imgLog.Visible = true;
			}
		}

		private void linkDevv_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			Process.Start("http://devv.com/");
		}

		#endregion

		#region Folder selection

		private void imgFolder_Click(object sender, EventArgs e)
		{
			if (Directory.Exists(Program.Options.FolderPath))
			{
				folderDialog.SelectedPath = txtPath.Text;
			}

			if (folderDialog.ShowDialog() == DialogResult.OK)
			{
				txtPath.Text = folderDialog.SelectedPath;
			}
		}

		private void txtPath_Leave(object sender, EventArgs e)
		{
			if (IOUtil.ValidatePhysicalPath(txtPath.Text))
			{
				Program.Options.FolderPath = txtPath.Text.Trim();
				txtPath.ForeColor = SystemColors.WindowText;
			}
			else
			{
				txtPath.ForeColor = Color.Red;
			}
		}

		private void txtFilter_Leave(object sender, EventArgs e)
		{
			Program.Options.FolderFilter = txtFilter.Text;
		}

		private void chkSubDir_CheckedChanged(object sender, EventArgs e)
		{
			Program.Options.IncludeSubDir = chkSubDir.Checked;
		}

		#endregion

		#region Smtp settings

		private void txtServer_Leave(object sender, EventArgs e)
		{
			Program.Options.SmtpServer = txtServer.Text;
		}

		private void numPort_Leave(object sender, EventArgs e)
		{
			Program.Options.SmtpPort = Convert.ToInt32(numPort.Value);
		}

		private void txtUser_Leave(object sender, EventArgs e)
		{
			Program.Options.SmtpUser = txtUser.Text;
		}

		private void txtPassword_Leave(object sender, EventArgs e)
		{
			Program.Options.SmtpPassword = txtPassword.Text;
		}

		private void chkSSL_CheckedChanged(object sender, EventArgs e)
		{
			Program.Options.SmtpSSL = chkSSL.Checked;
		}

		#endregion

		#region Email settings

		private void txtFrom_Leave(object sender, EventArgs e)
		{
			if (RegexUtil.Test(txtFrom.Text, RegexUtil.Email))
			{
				Program.Options.EmailFrom = txtFrom.Text;
				txtFrom.ForeColor = SystemColors.WindowText;
			}
			else
			{
				txtFrom.ForeColor = Color.Red;
			}
		}

		private void txtTo_Leave(object sender, EventArgs e)
		{
			if (RegexUtil.Test(txtFrom.Text, RegexUtil.Email))
			{
				Program.Options.EmailTo = txtTo.Text;
				txtTo.ForeColor = SystemColors.WindowText;
			}
			else
			{
				txtTo.ForeColor = Color.Red;
			}
		}

		private void txtSubject_Leave(object sender, EventArgs e)
		{
			Program.Options.EmailSubject = txtSubject.Text;
		}

		private void numPerMinute_Leave(object sender, EventArgs e)
		{
			Program.Options.PerMinute = Convert.ToInt32(numPerMinute.Value);
		}

		#endregion

		#region Monitor and send email

		private void butStop_Click(object sender, EventArgs e)
		{
			timerDelay.Stop();
			fsWatcher.EnableRaisingEvents = false;

			butStop.Enabled = false;
			butStart.Enabled = true;

			LogLine();
			Log(Messages.LogStop);
		}

		private void butStart_Click(object sender, EventArgs e)
		{
			if (!ValidateFields())
			{
				return;
			}

			String[] files = Directory.GetFiles(Program.Options.FolderPath);

			for (Int32 i = 0; i < files.Length; i++)
			{
				AddFile(files[i]);
			}

			timerDelay.Start();

			fsWatcher.Path = Program.Options.FolderPath;
			fsWatcher.IncludeSubdirectories = Program.Options.IncludeSubDir;
			fsWatcher.EnableRaisingEvents = true;

			butStart.Enabled = false;
			butStop.Enabled = true;

			LogLine();
			Log(Messages.LogStart);
			Log(Program.Options.FolderPath);
			LogLine();

			lblLogPath.Text = Messages.CurrentPath + " " + Program.Options.FolderPath;
			tabPages.SelectedIndex = 1;
		}

		private void fsWatcher_Changed(object sender, FileSystemEventArgs e)
		{
			AddFile(e.FullPath);
		}

		private void fsWatcher_Created(object sender, FileSystemEventArgs e)
		{
			AddFile(e.FullPath);
		}

		private void AddFile(String file)
		{
			if (Files.Contains(file))
			{
				return;
			}

			Files.Add(file);
		}

		private Boolean ValidateFields()
		{
			String fields = String.Empty;

			if (!Directory.Exists(txtPath.Text))
			{
				fields += Environment.NewLine + lblPath.Text;
			}

			if (!RegexUtil.Test(txtFrom.Text, RegexUtil.Email))
			{
				fields += Environment.NewLine + lblFrom.Text;
			}

			if (!RegexUtil.Test(txtTo.Text, RegexUtil.Email))
			{
				fields += Environment.NewLine + lblTo.Text;
			}

			if (!String.IsNullOrWhiteSpace(fields))
			{
				MessageBox.Show(Messages.PleaseCheckFields + Environment.NewLine + fields.Replace(":", String.Empty));

				return false;
			}

			return true;
		}

		#endregion

		#region Send email

		private void timerDelay_Tick(object sender, EventArgs e)
		{
			timerDelay.Stop();
			timerDelay.Interval = 30 / Program.Options.PerMinute * 1000;

			if (Files.Count > 0)
			{
				SendEmail(Files[0]);
			}

			if (LastSent.AddSeconds(60) < DateTime.Now)
			{
				SentCount = SentCount / 2;
			}

			if (SentCount > Program.Options.PerMinute)
			{
				timerDelay.Interval = 60000;
			}

			timerDelay.Start();
		}

		private void SendEmail(String file)
		{
			Files.Remove(file);

			MailMessage msg = new MailMessage();

			try
			{
				msg.IsBodyHtml = false;
				msg.Body = Resources.EmailTemplate;
				msg.Attachments.Add(new Attachment(file));
				msg.From = new MailAddress(Program.Options.EmailFrom);

				String[] to = Program.Options.EmailTo.Split(",".ToCharArray());

				for (Int32 i = 0; i < to.Length; i++)
				{
					msg.To.Add(new MailAddress(to[i]));
				}

				if (!String.IsNullOrWhiteSpace(Program.Options.EmailSubject))
				{
					msg.Subject = Program.Options.EmailSubject;
				}
				else
				{
					msg.Subject = Path.GetFileName(file);
				}
			}
			catch (Exception ex)
			{
				Log(ex);
			}

			try
			{
				SmtpClient smtp = new SmtpClient();

				smtp.Host = Program.Options.SmtpServer;
				smtp.Port = Program.Options.SmtpPort;
				smtp.EnableSsl = Program.Options.SmtpSSL;

				if (!String.IsNullOrWhiteSpace(Program.Options.SmtpUser) && !String.IsNullOrWhiteSpace(Program.Options.SmtpPassword))
				{
					smtp.Credentials = new NetworkCredential(Program.Options.SmtpUser, Program.Options.SmtpPassword);
				}

				MailUtil.Send(msg, true, smtp);

				Log(file);

				Sent.Add(file);
			}
			catch (Exception ex)
			{
				Log(Path.GetFileName(file) + " " + Messages.Error + ": " + ex);
			}

			LastSent = DateTime.Now;
		}

		#endregion

		#region Logging

		private void butClearLog_Click(object sender, EventArgs e)
		{
			txtLog.Text = String.Empty;

			Log(Messages.LogCleared);
		}

		private void LogLine()
		{
			Log(Messages.LogLine);
		}

		private void Log(Exception ex)
		{
			Log(ex.ToString(), true);
		}

		private void Log(String text, Boolean extraLine = false)
		{
			String t = Environment.NewLine + text;

			if (extraLine)
			{
				t += Environment.NewLine;
			}
			txtLog.Text += t;
		}

		#endregion
	}
}